package com.zb.frame.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zb.frame.modules.common.vo.RouterMenuVO;
import com.zb.frame.modules.sys.entity.Menu;
import com.zb.frame.modules.sys.mapper.MenuMapper;
import com.zb.frame.modules.sys.mapper.RelRoleMenuMapper;
import com.zb.frame.modules.sys.service.MenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.frame.modules.sys.vo.MenuTreeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author bangZZ
 * @since 2020-06-04
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    MenuMapper menuMapper;

    @Autowired
    RelRoleMenuMapper roleMenuMapper;

    /**
     * 获取所有的资源(目录/菜单/操作)
     * @return
     */
    @Override
    public List<MenuTreeVO> getAllList(){
        return menuMapper.getAllList();
    }

    /**
     * 根据Id获取资源信息(目录/菜单/操作)
     * @return
     */
    @Override
    public Menu getMenuById(Long id) {
        return menuMapper.getMenuById(id);
    }

    @Override
    public boolean isExistName(String menuName) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<Menu>();
        wrapper.eq("menu_name", menuName);
        return this.count(wrapper) > 0;
    }

    @Override
    public Menu addResource(Menu data) {
        Menu menu = new Menu();
        menu.setMenuName(data.getMenuName());
        menu.setMenuAlias(data.getMenuAlias());
        menu.setPId(data.getPId());
        menu.setMenuType(data.getMenuType());
        menu.setMenuIcon(data.getMenuIcon());
        menu.setMenuPath(data.getMenuPath());
        menu.setMenuPerm(data.getMenuPerm());
        menu.setMenuOrder(data.getMenuOrder());
        menu.setMenuDesc(data.getMenuDesc());
        return this.save(menu) ? menu : null;
    }

    @Override
    public Menu updateRole(Menu data) {
        Menu menu = new Menu();
        menu.setMenuId(data.getMenuId());
        // menu.setMenuName(data.getMenuName());
        menu.setMenuAlias(data.getMenuAlias());
        menu.setPId(data.getPId());
        // menu.setMenuType(data.getMenuType());
        menu.setMenuIcon(data.getMenuIcon());
        menu.setMenuPath(data.getMenuPath());
        menu.setMenuPerm(data.getMenuPerm());
        menu.setMenuOrder(data.getMenuOrder());
        menu.setMenuDesc(data.getMenuDesc());
        boolean f = this.updateById(menu);
        return f ? menu : null;
    }

    @Override
    public boolean isExistChildren(Long menuId) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<Menu>();
        wrapper.eq("p_id", menuId);
        return this.count(wrapper) > 0;
    }

    /**
     * 获取用户的[操作权限](perm)
     * @param roles 用户角色列表
     * @return ['XXX','XXX',...]
     */
    @Override
    public Set<String> getUserPermission(Set<String> roles) {
        if (roles.contains("ADMIN")) {
            // 角色[超级管理员]获取所有操作权限
            return menuMapper.getAllPerm();
        } else {
            // 角色获取其拥有的操作权限
            return menuMapper.getUserPerm(roles);
        }
    }

    /**
     * 获取用户的[权限菜单](Menu)
     * @param roles 用户角色列表
     * @return ['XXX','XXX',...]
     */
    @Override
    public List<RouterMenuVO> getUserMenuList(Set<String> roles) {
        // 角色[超级管理员]获取所有菜单
        if(roles.contains("ADMIN")){
            return getAllMenuList(null);
        }
        // 角色获取其拥有的权限菜单
        // 根据角色列表获取资源(目录+菜单)Id列表
        List<Long> menuIds = roleMenuMapper.getMenuIdsByRoles(roles);
        return getAllMenuList(menuIds);
    }

    /**
     * 获取所有菜单列表
     */
    private List<RouterMenuVO> getAllMenuList(List<Long> menuIdList){
        //查询根菜单(上级主键为0)列表
        List<RouterMenuVO> menuList = getRootMenuByPid(0L, menuIdList);
        //递归获取子菜单
        getMenuTreeList(menuList, menuIdList);
        return menuList;
    }

    /**
     * 根据上级资源主键查询该资源下所有子资源，并进行筛选
     * @param parentId
     * @return
     */
    private List<RouterMenuVO> getRootMenuByPid(Long parentId, List<Long> menuIds) {
        List<RouterMenuVO> menuList = getRootMenuByPid(parentId);
        if (menuIds == null)
            return menuList;
        List<RouterMenuVO> ret = new ArrayList<>();
        for(RouterMenuVO routerMenu : menuList){
            if(menuIds.contains(routerMenu.getId())){
                ret.add(routerMenu);
            }
        }
        return ret;
    }

    /**
     * 根据上级资源主键查询该资源下所有子资源
     * @param parentId
     * @return
     */
    private List<RouterMenuVO> getRootMenuByPid(Long parentId) {
        return menuMapper.getRouterMenuByPid(parentId);
    }

    /**
     * 递归查询子菜单
     */
    private List<RouterMenuVO> getMenuTreeList(List<RouterMenuVO> menuList, List<Long> menuIdList){
        List<RouterMenuVO> subMenuList = new ArrayList<>();
        for(RouterMenuVO menu : menuList){
            if(menu.getType() == 1){
                menu.setChildren(getMenuTreeList(getRootMenuByPid(menu.getId(),menuIdList),menuIdList));
            }
            subMenuList.add(menu);
        }
        return subMenuList;
    }

}
